Next | Prev | Up | Top | Contents | Index

Probing the Address Space

The sample program in Example A-7 uses some generally unsafe coding tricks to get the addresses of segments for text, stack, library DSO and mapped data. It demonstrates the use of mmap() with /dev/zero, for default and absolute segment addresses.

Example A-7 : Program That Explores the Address Space

#include <stddef.h>     /* for standard malloc(3C) */
#include <unistd.h>     /* for sbrk(2) */
#include <stdio.h>      /* for printf */
#include <sys/types.h>  /* for __psint_t */
/* include <sys/stat.h> */
#include <sys/fcntl.h>  /* for O_RDWR */
#include <sys/mman.h>   /* for mmap(2) */
#define DISPLAY(v,t) {printf("%s:\t%0lx\n",t,(__psint_t)v);}
int main()
{
    /*
    || Get a mask that truncates an address to a page boundary.
    */
    __psint_t psize = getpagesize();
    __psint_t pmask = ~(psize-1);
    /*
    || Get a file descriptor for the nothing device.
    || Use that FD to map two segments of memory containing 00.
    */
    int zero = open("/dev/zero",O_RDWR);
    void * zmap1 = mmap(0,16384,PROT_WRITE,MAP_SHARED,zero,0);
    void * zmap2 = mmap(0,16384,PROT_WRITE,MAP_SHARED,zero,0);
    /*
    || Map one segment at a designated address reserved for
    || user maps by the MIPS ABI.
    */
    void * abi_map = (char *)mmap((void *)0x30040000L,16384,
                PROT_WRITE,MAP_SHARED+MAP_FIXED,zero, 0);

    /*
    || Get the address of this program.
    */
    char * poke = (char *)((__psint_t)main);
    /*
    || Get some program addresses supplied by ld(1), but note
    || the warnings in end(3C) -- these addresses "have no standard
    || definition" when multiple text/data segments exist.
    */
    extern int _ftext[];
    void * ld_ftext = (void *)_ftext;
    extern int _etext[];
    void * ld_etext = (void *)_etext;
    extern int _fdata[];
    void * ld_fdata = (void *)_fdata;
    extern int _edata[];
    void * ld_edata = (void *)_edata;
    extern int _fbss[];
    void * ld_fbss  = (void *)_fbss;
    extern int _end[];
    void * ld_end   = (void *)_end;
    /*
    || Get the address of some code in the libc DSO.
    */
    void * libc_adr = (void *)fprintf;
    /*
    || Get the current start and end of the heap.
    */
    void * malloc_adr = (void *)malloc((size_t)256);
    void * brk_adr = sbrk(0);
    /*
    || Get the address of an item in our stack space.
    */
    void * stack_adr = (void *)&psize;
    /*
    || Display all the above.
    */
    DISPLAY(psize,"Page size")
    DISPLAY(zmap1,"Mapped segment 1")
    DISPLAY(zmap2,"Mapped segment 2")
    DISPLAY(abi_map,"ABI mapped segment")
    DISPLAY(ld_ftext,"Text starts")
    DISPLAY(ld_etext,"Text ends")
    DISPLAY(ld_fdata,"Initialized data starts")
    DISPLAY(ld_edata,"Initialized data ends")
    DISPLAY(ld_fbss,"Uninitialized starts")
    DISPLAY(ld_end,"Uninitialized ends")
    DISPLAY(malloc_adr,"Heap data starts")
    DISPLAY(brk_adr,"Heap data ends")
    DISPLAY(stack_adr,"Stack data")
    DISPLAY(libc_adr,"Spot in one DSO")
    /*
    || See if we can get away with patching our own text.
    */
    if (!mprotect((void *)(pmask&(__psint_t)poke),psize,PROT_WRITE+PROT_EXEC))
    {
        poke[0] = poke[0];
        printf("I wrote into program text\n");
    }
    else
    {
        perror("mprotect(text)");
    }
}


Next | Prev | Up | Top | Contents | Index